<!--
 * @Author: liyin 2179253556@qq.com
 * @Date: 2022-11-11 16:31:49
 * @LastEditors: liyin 2179253556@qq.com
 * @LastEditTime: 2025-07-31 09:23:36
 * @FilePath: ApiList.vue
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
    <div class="user-info-box">
        <Table :marginTop="false" :data="tableData" :config="tableConfig" @handleEdit="handleEdit" :showPage="false">
            <el-button type="primary" @click="Add">
                添加菜单
            </el-button>
        </Table>
        <!-- 添加路由弹窗 -->
        <Model :title="addForm.uuid ? '编辑菜单' : '添加菜单'" :modelShow="dialogVisible" width="40"
            @cancel="resetForm(ruleFormRef)" @confirm="submitForm(ruleFormRef)">
            <el-form label-width="110px" size="default" :rules="rules" :model="addForm" ref="ruleFormRef">
                <el-form-item label="菜单名称" prop="menu_name">
                    <el-input v-model="addForm.menu_name" placeholder="请输入菜单名称" />
                </el-form-item>
                <!-- <el-form-item label="栏目类型" prop="type">
                    <el-select :teleported="false" v-model="addForm.type" style="width:100%;" clearable
                        placeholder="请选择栏目类型">
                        <el-option label="菜单" value="1"></el-option>
                        <el-option label="按钮" value="2"></el-option>
                    </el-select>
                </el-form-item> -->
                <el-form-item label="关联父级/菜单" v-if="!addForm.uuid||(addForm.uuid && addForm.parent_uuid && Number(addForm.parent_uuid)!=0)">
                    <el-cascader v-model="pids" :options="tableData" clearable :props="{
                        expandTrigger: 'click',
                        checkStrictly: true,
                        value: 'uuid',
                        label: 'menu_name',
                        children: 'children'
                    }" @change="handleChange" style="width:100%" :teleported="false" placeholder="请选择关联父级/菜单"></el-cascader>
                </el-form-item>
                <el-form-item label="路由地址" v-if="Number(addForm.type) == 1" prop="component">
                    <el-input v-model="addForm.component" placeholder="请输入路由地址" />
                </el-form-item>
                <el-form-item label="路由地址" v-if="Number(addForm.type) == 2" prop="path">
                    <el-input v-model="addForm.path" placeholder="请输入路由地址(后台)" />
                </el-form-item>
                <el-form-item label="请求方式" v-if="Number(addForm.type) == 2" prop="path">
                    <el-select :teleported="false" v-model="addForm.request_method" style="width:100%;" clearable
                        placeholder="请选择请求方式">
                        <el-option label="GET" value="GET"></el-option>
                        <el-option label="POST" value="POST"></el-option>
                        <el-option label="PUT" value="PUT"></el-option>
                        <el-option label="DELETE" value="DELETE"></el-option>
                    </el-select>
                </el-form-item>
                <el-row>
                    <el-form-item label="栏目图标" required v-if="Number(addForm.type) == 1 && (!pids || pids.length==0)">
                        <span v-if=" addForm.icon" :class="'icon iconfont ' + addForm.icon" style="width:32px;height:32px;border: 1px solid #dcdfe6;box-sizing: border-box;text-align: center;border-radius: 4px;margin-right:15px;"></span>
                        <el-button type="primary" size="default" @click="changeIcon">
                            <el-icon style="vertical-align: middle;">
                                <Refresh />
                            </el-icon>
                            <span style="vertical-align: middle">{{
                                addForm.icon != '' && addForm.icon !== null
                                ? '点击更换'
                                : '点击选择'
                                }}</span>
                        </el-button>
                    </el-form-item>
                    <el-form-item label="状态" prop="status">
                        <el-radio-group v-model="addForm.status" size="default">
                            <el-radio-button label="1">有效</el-radio-button>
                            <el-radio-button label="0">无效</el-radio-button>
                        </el-radio-group>
                    </el-form-item>
                </el-row>
            </el-form>
        </Model>
        <!-- 选择图标抽屉 -->
        <el-drawer v-model="drawer" title="icon图标集合，点击可复制" :direction="direction">
            <IconDemo @selectchangeIcon="selectchangeIcon"></IconDemo>
        </el-drawer>
    </div>
</template>
<script setup lang="ts">
import { ref, h, onMounted, reactive, nextTick } from 'vue'
import type { FormInstance, FormRules } from 'element-plus'
import { ElMessage, ElMessageBox } from 'element-plus'
// 引入专属的request配置
import { ApiList, addMenus, editMenus, delMenus, sortMenu } from '../../components/Api/Operation'
// import iconJson from '../../assets/fonts/iconfont.json'
import IconDemo from '../IconDemo/index.vue'
import { PiniaStore } from '../../store'
const store = PiniaStore()
const personQuery = reactive({
    getTree: 'getTree',
    page: 1,
    page_size: 10
})
const drawer = ref(false)
const direction = ref('rtl')
const dialogVisible = ref(false)
const ruleFormRef = ref<FormInstance>()
const addForm = reactive({
    uuid: '',
    parent_uuid: '',
    menu_name: '',
    path: '',
    request_method: '',
    component: '',
    perms: 'test',
    icon: '',
    type: '1',
    status:'1'
})
const pids = ref<any>([])
const rules = reactive<FormRules>({
    menu_name: [{ required: true, message: '请输入菜单名称', trigger: 'blur' }],
    path: [{ required: true, message: '请输入路由地址(后台)', trigger: 'change' }],
    component: [{ required: true, message: '请输入路由地址(前台)', trigger: 'change' }],
    type: [{ required: true, message: '请选择栏目类型', trigger: 'blur' }],
})
const tableData = ref([])
const tableConfig = ref([
    { name: 'menu_name', label: '菜单名称', width: '',  checked: true },
    { name: 'component', label: '路由地址', width: '', type:'change',checked: true },
    // { name: 'path', label: '路由地址(后台)', width: '', type:'change',checked: true },
    // { name: 'request_method', label: '请求方式', width: '', type: 'change', checked: true },
    { name: 'icon', type: "icon", label: '栏目图标', width: '', checked: true },
    // { name: 'sort', label: '排序', width: '', checked: true },
    // {
    //     name: 'type',
    //     label: '类型',
    //     width: '',
    //     checked: true,
    //     type: 'status',
    //     formatter: [
    //         { name: '1', label: '菜单', status: 'primary' },
    //         { name: '2', label: '按钮', status: 'success' }
    //     ]
    // },
    {
        name: 'status',
        label: '状态',
        width: '',
        checked: true,
        type: 'status',
        formatter: [
            { name: 0, label: '无效', status: 'danger' },
            { name: 1, label: '有效', status: 'success' }
        ]
    },
    {
        name: '',
        label: '操作',
        width: '200',
        type: 'edit',
        checked: true,
        formatter: [
            { name: 'Edit', label: '编辑', font: true, link: true },
            { name: 'Delete', label: '删除', font: true, link: true },
            { name: 'Top', label: '上移', font: true, link: true },
            { name: 'Bottom', label: '下移', font: true, link: true },
        ]
    }
])
const changeIcon = async () => {
    drawer.value = true
}
const Add = async () => {
    addForm.uuid = ''
    addForm.parent_uuid= '0'
    addForm.icon = ''
    dialogVisible.value = true
}
const handleChange = (val: any) => {
    if (val && val.length > 0) {
        let str: any = []
        str.push(val[val.length - 1])
        addForm.parent_uuid = str.join(',')
    } else {
        addForm.parent_uuid = ''
    }
}
// 获取菜单列表
const getApiList = async () => {
    const res: any = await ApiList(personQuery)
    if (res.code !== 1) return ElMessage.error(res.message)
    tableData.value = res.data
}
const submitForm = async (formEl: FormInstance | undefined) => {
    if (!formEl) return
    formEl.validate(async (valid: any) => {
        if (valid) {
            const res: any = addForm.uuid ? await editMenus(addForm) : await addMenus(addForm)
            if (res.code !== 1) return ElMessage.error(res.message)
            ElMessage.success(res.message)
            dialogVisible.value = false
            getApiList()
            resert()
            formEl.resetFields()
        } else {
            console.log('error submit!')
        }
    })
}
const resetForm = (formEl: FormInstance | undefined) => {
    if (!formEl) return
    dialogVisible.value = false
     resert()
    formEl.resetFields()
}
const resert= async () => {
    addForm.uuid = ''
    addForm.parent_uuid = '0'
    addForm.menu_name= ''
    addForm.path = ''
    addForm.request_method = ''
    addForm.component = ''
    addForm.perms = ''
    addForm.icon = ''
    addForm.type = '1'
    addForm.status = '1'
    pids.value=[]
}
// 点击菜单上移/下移
const sortChange = async (item: any, type: string) => {
    const params = {
        type: type == 'Top' ? 'up' : 'down',
        parent_uuid: item.parent_uuid,
        uuid: item.uuid,
        sort: item.sort,
    }
    const res: any = await sortMenu(params)
    if (res.code !== 1) return ElMessage.error(res.message)
    ElMessage.success(res.message)
    getApiList()
}
const handleEdit = (item: any, name: string) => {
    if (name === 'Edit') {
        // 编辑
        dialogVisible.value = true
        nextTick(() => {
            addForm.uuid = item.uuid
            addForm.parent_uuid = item.parent_uuid
            addForm.menu_name = item.menu_name
            addForm.path = item.path
            addForm.request_method = item.request_method
            addForm.component = item.component
            addForm.perms = item.perms
            addForm.icon = item.icon
            addForm.type = item.type
            addForm.status = item.status
            // 路由结构回显
            if (item.parent_uuid !== '') {
                pids.value = []
                const arr = getAllParentArr(tableData.value, item.parent_uuid)
                arr.reverse().forEach((item: any) => {
                    pids.value.push(item.uuid)
                })
            }
            addForm.parent_uuid = pids.value[pids.value.length-1]
        })
    } else if (name === 'Delete') {
        // 删除
        ElMessageBox({
        title: '温馨提示',
        message: h('p', { style: 'font-weight:bold;font-size: 15px;color: #333333;' }, [
                h('span', null, '确定要删除？'),
                h('p', { style: 'font-size: 14px;font-weight:normal;color: rgba(0,0,0,0.65);margin-top:10px;' }, '删除后将无法恢复，确定要继续吗?'),
            ]),
            showCancelButton: true,
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning',
            beforeClose: async (action, instance, done) => {
                if (action === 'confirm') {
                    const res: any = await delMenus({ uuid: item.uuid })
                if (res.code !== 1) return ElMessage.error(res.message)
                ElMessage.success(res.message)
                getApiList()
                    done()
                } else {
                    done()
                }
            },
        }).then((action) => {
        })
        } else if (name === 'Top' || name === 'Bottom') {
            // 其他可自行添加
            sortChange(item, name)
        }
}
const getAllParentArr = (list: any, uuid: string | number) => {
    for (const i in list) {
        if (list[i].uuid === uuid) {
            // 查询到返回该数组对象
            // console.log(list[i])
            return [list[i]]
        }
        if (list[i].children) {
            const node: any = getAllParentArr(list[i].children, uuid)
            if (node !== undefined) {
                // 查询到把父节点连起来
                return node.concat(list[i])
            }
        }
    }
}
const selectchangeIcon = (val: string) => {
    addForm.icon = val
    drawer.value = false
}
onMounted(() => {
    store.setSearchHeight(0)
    store.setTableHeight()
    getApiList()
})
</script>
<style lang="scss" scoped>
.user-info-box {
    width: 100%;
}

ul li {
    list-style: none;
}

.icon_ul {
    margin-left: -40px;
    display: flex;
    flex-wrap: wrap;
    overflow: hidden;

    li {
        width: 80px;
        background-color: #f9f9f9;
        border: 1px solid var(--el-color-white);
        padding: 20px 5px 10px;
        text-align: center;
        // flex: auto;
        cursor: pointer;
        position: relative;

        .icon_svg {
            position: relative;
            left: 50%;
            transform: translateX(-50%);
        }

        .title {
            display: block;
            text-align: center;
            word-wrap: break-word;
            margin-top: 10px;
            font-size: 12px;
        }

        &:hover {
            color: var(--el-color-white);
            background-color: #3b95ff;
        }
    }
}
</style>